package modele;

import java.io.Serializable;
import java.util.ArrayList;
import controleur.Controleur;

import modele.Batiment.Batiment;
import modele.Unite.UniteAttaquante;
import modele.Unite.Ouvrier;

public class Joueur implements Serializable{
	private static final long serialVersionUID = -7980925573100459754L;
	Partie partie;
	ArrayList<Batiment> listeBatiment;
	ArrayList<UniteAttaquante> listeUniteAttaquante;
	ArrayList<Ouvrier> listeOuvrier;
	int ressourceOr = 5000;
	int ressourceElixir = 5000;
	//Batiment batimentSelectionne;		//référence seulement
	//Ouvrier ouvrierSelectionne;			//référence seulement
	int nbrBatimentsRestant = 0;
	
	public void setNbrBatimentsRestant(int nbrBatimentsRestant) {
		this.nbrBatimentsRestant = nbrBatimentsRestant;
	}

	public Joueur(Partie partie)
	{
		this.partie = partie;
		listeBatiment = new ArrayList<Batiment>();
		listeUniteAttaquante = new ArrayList<UniteAttaquante>();
		listeOuvrier = new ArrayList<Ouvrier>();
	}
	
	public void collecterOr(int quantiteOr)
	{
		int capaciteStockage = 0;
		for(int i = 0; i < listeBatiment.size(); i++)
		{
			capaciteStockage = capaciteStockage + listeBatiment.get(i).getCapaciteStockageOr();
		}
		if(capaciteStockage < this.getRessourceOr() + quantiteOr)
			this.setRessourceOr(capaciteStockage);
		else
			this.setRessourceOr(this.getRessourceOr() + quantiteOr);
	}
	
	
	public void collecterElixir(int quantiteElixir)
	{
		int capaciteStockage = 0;
		for(int i = 0; i < listeBatiment.size(); i++)
		{
			capaciteStockage = capaciteStockage + listeBatiment.get(i).getCapaciteStockageElixir();
		}
		if(capaciteStockage < this.getRessourceElixir() + quantiteElixir)
			this.setRessourceElixir(capaciteStockage);
		else
			this.setRessourceElixir(this.getRessourceElixir() + quantiteElixir);
	}
	
	public void ajouterBatiment(Batiment batiment)
	{
		this.listeBatiment.add(batiment);
		nbrBatimentsRestant++;
	}
	
	/**
	 * ajoute l'unité attaquante à la liste du joueur
	 * @param uniteAttaquante unité attaquante à ajouter
	 */
	public void ajouterUniteAttaquante(UniteAttaquante uniteAttaquante)
	{
		this.listeUniteAttaquante.add(uniteAttaquante);
	}

	public ArrayList<UniteAttaquante> getListeUniteAttaquante() {
		return listeUniteAttaquante;
	}

	public void setListeUniteAttaquante(
			ArrayList<UniteAttaquante> listeUniteAttaquante) {
		this.listeUniteAttaquante = listeUniteAttaquante;
	}

	public ArrayList<Ouvrier> getListeOuvrier() {
		return listeOuvrier;
	}

	public void setListeOuvrier(ArrayList<Ouvrier> listeOuvrier) {
		this.listeOuvrier = listeOuvrier;
	}

	public int getRessourceOr() {
		return ressourceOr;
	}

	public void setRessourceOr(int ressourceOr) {
		this.ressourceOr = ressourceOr;
	}

	public int getRessourceElixir() {
		return ressourceElixir;
	}

	public void setRessourceElixir(int ressourceElixir) {
		this.ressourceElixir = ressourceElixir;
	}
	
	public int getRessourceOrMax()
	{
		int somme = 0;
		for(int i=0;i<this.listeBatiment.size();i++)
		{
			somme += this.listeBatiment.get(i).getCapaciteStockageOr();
		}
		return somme;
	}
	
	public int getRessourceElixirMax()
	{
		int somme = 0;
		for(int i=0;i<this.listeBatiment.size();i++)
		{
			somme += this.listeBatiment.get(i).getCapaciteStockageElixir();
		}
		return somme;
	}
	
	public int getProductionParSecondeElixirTotal()
	{
		int somme = 0;
		for(int i=0;i<this.listeBatiment.size();i++)
		{
			somme += this.listeBatiment.get(i).getProductionParSecondeElixir();
		}
		return somme;
	}
	
	public int getProductionParSecondeOrTotal()
	{
		int somme = 0;
		for(int i=0;i<this.listeBatiment.size();i++)
		{
			somme += this.listeBatiment.get(i).getProductionParSecondeOr();
		}
		return somme;
	}
	
	
	public int getNbUniteSoldat()
	{
		int somme=0;
		for(int i=0; i<this.listeUniteAttaquante.size();i++)
		{
			if(this.listeUniteAttaquante.get(i).getClass().getName().equals("modele.Unite.Soldat")) somme += 1;
		}
		return somme;
	}
	
	public int getNbUniteArcher()
	{
		int somme=0;
		for(int i=0; i<this.listeUniteAttaquante.size();i++)
		{
			if(this.listeUniteAttaquante.get(i).getClass().getName().equals("modele.Unite.Archer")) somme += 1;
		}
		return somme;
	}
	
	public int getNbUniteGobelin()
	{
		int somme=0;
		for(int i=0; i<this.listeUniteAttaquante.size();i++)
		{
			if(this.listeUniteAttaquante.get(i).getClass().getName().equals("modele.Unite.Gobelin")) somme += 1;
		}
		return somme;
	}
	
	public int getNbUniteGeant()
	{
		int somme=0;
		for(int i=0; i<this.listeUniteAttaquante.size();i++)
		{
			if(this.listeUniteAttaquante.get(i).getClass().getName().equals("modele.Unite.Geant")) somme += 1;
		}
		return somme;
	}

	
	public int getNbUniteMax()
	{		
		int somme=0;
		for(int i=0; i<this.listeBatiment.size();i++)
		{
			if(this.listeBatiment.get(i).getClass().getName().equals("modele.Batiment.CampMilitaire")) somme += 30 + (this.listeBatiment.get(i).getNiveau()-1)*10;
		}
		return somme;
	}
	/**
	 * 
	 * @param batiment Batiment à créer, il doit contenir sa position
	 */
	public void creerBatiment(Controleur controleur, Batiment batiment, Map map)
	{
		//TODO quand on gèrera les timer
		//ici il faut selectionner un ouvrier
		//Ouvrier ouvrierSelectionne = this.listeOuvrier.get(0);
		//ouvrierSelectionne.construireBatiment(controleur, this, batiment, map);
		
		map.marquerCreationBatiment(batiment);
		ajouterBatiment(batiment);//ajout dans la liste
	}
	
	void lancerAttaque()
	{
		
	}
	
	public ArrayList<Batiment> getListeBatiment() {
		return listeBatiment;
	}

	public void setListeBatiment(ArrayList<Batiment> listeBatiment) {
		this.listeBatiment = listeBatiment;
	}
	
	/**
	 * 
	 * @param batiment batiment à payer
	 * @return 0 si le paiement ne peut pas avoir lieu, 1 si le paiement est effectué
	 */
	public int payerBatiment(Batiment batiment) {
		if(batiment.getCoutConstructionOr() < getRessourceOr() && batiment.getCoutConstructionElixir() < getRessourceElixir())
		{
			setRessourceOr(getRessourceOr()-batiment.getCoutConstructionOr());
			setRessourceElixir(getRessourceElixir()-batiment.getCoutConstructionElixir());
			return 1;
		}
		else
		{
			return 0;
		}
	}
	
	/**
	 * cette méthode est appelée lorsque lors d'une attaque un batiment est détruit
	 * elle calcule le nombre de batiments non détruits dynamiquement
	 * si ce nombre vaut 0 alors
	 * @param batiment batiment détruit
	 */
	public void perdreBatiment(Batiment batiment) {
		//TODO
		nbrBatimentsRestant--;
		partie.getListeBatimentJoueurEnnemi().remove(batiment);
		System.out.println("Il reste "+nbrBatimentsRestant+" batiments en defense");
		if(nbrBatimentsRestant == 0)
		{
			partie.gagnerBataille();
		}
		
	}
	
	public void incrementerNbrBatimentsRestant()
	{
		nbrBatimentsRestant++;
	}
	
	public int getNbrBatimentsRestant()
	{
		return nbrBatimentsRestant;
	}

	public void perdreUniteAttaquante(UniteAttaquante uniteAttaquante) {
		this.listeUniteAttaquante.remove(uniteAttaquante);
		uniteAttaquante.getCamp().getListeUniteAttaquante().remove(uniteAttaquante);
		
		if(listeUniteAttaquante.size() == 0)
		{
			//fin de l'attaque
			partie.perdreBataille();
		}
	}

	public void ajouterOuvrier(Ouvrier ouvrier) {
		listeOuvrier.add(ouvrier);
	}
	
	/**
	 * renvoie un ouvrier près à construire
	 * @return un ouvrier s'il y en a un, null sinon
	 */
	public Ouvrier getConstructeur() {
		//TODO
		if(!listeOuvrier.get(0).estEnTrainDeConstruire())
			return listeOuvrier.get(0);
		else
			return null;
	}
	
	
	
}
